/*global pi */

// 应用程序运行框架
pi.mod.define('pi.render.run', function (pi) {
	"use strict";
	var paintLoop, renderContext, updatePage, paintCallback, renderPage, resizeCallback, createRenderRes, sendRender, sceneDraw, sceneReize, initCallback, draw2DQuad, module = {},
		isRendering = false,

		// 页面纹理
		pageTex = 0,

		pageWidth = 0,
		pageHeight = 0,
		browserWin = 0,

		/* 地形的扩展块的最大数量 */
		TERRAIN_EXT_NUM = 8,

		/* 传送指令开始 */
		RENDER_BEGIN = 0,

		/* 传送指令结束 */
		RENDER_END = 1,

		/* 相机 */
		RENDER_3D_CAMERA = 2,

		/* 天空盒 */
		RENDER_3D_SKYBOX = 3,

		/* 地形 */
		RENDER_3D_TERRAIN = 4,

		/* 网格 */
		RENDER_3D_MESH = 5,

		/* 粒子系统 */
		RENDER_3D_PARSYS = 6,

		/* 骨骼轨迹 */
		RENDER_3D_SKTRAIL = 7,

		/* 灯光 */
		RENDER_3D_LIGHT = 8,

		/* 宽、高信息 */
		RENDER_2D_SIZE = 9,

		/* 四边形 */
		RENDER_2D_QUAD = 10,

		/* 缓冲区溢出检查标记 */
		CHECK_OVERFLOW_FLAG = 0xcccccccc;

	// 返回成功或者失败
	draw2DQuad = function (buf, x, y, z, w, h, tex) {
		pi.cbuffer.writeInt8(buf, RENDER_2D_QUAD);
		pi.cbuffer.writeFloat(buf, x);
		pi.cbuffer.writeFloat(buf, y);
		pi.cbuffer.writeFloat(buf, z);
		pi.cbuffer.writeFloat(buf, w);
		pi.cbuffer.writeFloat(buf, h);
		pi.cbuffer.writeInt8(buf, 255);
		pi.cbuffer.writeInt8(buf, 255);
		pi.cbuffer.writeInt8(buf, 255);
		pi.cbuffer.writeInt8(buf, 255);
		pi.cbuffer.writePointer(buf, tex);
		pi.cbuffer.writeInt(buf, CHECK_OVERFLOW_FLAG);
	};

	// 发送渲染指令
	sendRender = function (buf) {
		var p = {
			handle: buf,
			context: renderContext
		};

		// 发送渲染指令到计算线程
		pi.worker.handle.compute(p, function (rBuf) {
			pi.cbuffer.destroy(buf);
			if (rBuf.error !== undefined) {
				pi.log("pi.worker.handle.compute failed");
			} else {
				p = {
					bytes: rBuf,
					context: renderContext
				};

				// 表示正在渲染
				isRendering = true;

				// 发送渲染指令到渲染缓冲区
				pi.worker.handle.render(p, function (isOK) {
					isRendering = false;
					pi.cbuffer.destroy(rBuf);
				});
			}
		});
	};

	updatePage = function () {
		var h, img;
		if (pageWidth > 0 && pageHeight > 0) {
			img = pi.render.t3d.createImg(pageWidth, pageHeight);
			h = pi.render.t3d.getImgHandle(img);
			pi.browser.paint(pi.vcall.webViewHandle, h, pageWidth, pageHeight);
			pi.worker.handle.updateTex(pageTex, img, function () {
				pi.render.t3d.destroyImg(img);
			});
		}
	};

	renderPage = function (buf) {
		// 设置宽高：视口矩阵和投影矩阵
		pi.cbuffer.writeInt8(buf, RENDER_2D_SIZE);
		pi.cbuffer.writeInt(buf, pageWidth);
		pi.cbuffer.writeInt(buf, pageHeight);
		pi.cbuffer.writeInt(buf, CHECK_OVERFLOW_FLAG);

		draw2DQuad(buf, 0, 0, 0.99, pageWidth, pageHeight, pageTex);
	};

	// C层收到WM_PAINT的回调
	paintCallback = function () {

		if (pageTex === 0 || pageWidth <= 0 || pageHeight <= 0) {
			return;
		}

		if (pi.browser.isDirty(pi.vcall.webViewHandle)) {
			updatePage();
		}

		if (!isRendering) {
			if (sceneDraw && renderContext) {
				sceneDraw(renderContext);
			}
		}
	};



	paintLoop = function () {
		paintCallback();
		pi.lang.setTimeout(paintLoop, 17);
	};

	// C层需要扩展大小的回调
	resizeCallback = function (w, h) {
		pageWidth = w;
		pageHeight = h;
		updatePage();
		if (sceneReize) {
			sceneReize(w, h);
		}
	};

	// 得到渲染句柄后的回调
	createRenderRes = function (context) {
		var s;
		if (context.error !== undefined) {
			s = "pi.render.run init createRenderRes: create context failed.";
			pi.log(s);
		} else {

			renderContext = context;

			pi.worker.handle.createTex(1, 1, function (tex) {
				if (tex.error !== undefined) {
					pi.log("pi.render.run init createRenderRes, create tex failed.");
				} else {
					pageTex = tex.data;

					// 初始化的回调
					initCallback(renderContext);

					pi.browser.setCallback(pi.vcall.webViewHandle, paintCallback, resizeCallback);
				}
			});

			paintLoop();
		}
	};

	// 切换页面、刷新页面、退出页面时候，需要调用这个函数
	module.clear = function () {
		pi.browser.setCallback(pi.vcall.webViewHandle, null, null);
		pi.worker.handle.destroyContext(renderContext, function () {});
		pi.worker.handle.clear();
	};

	// callback是带有参数：renderContext的回调
	module.init = function (callback) {

		// 初始化线程
		pi.worker.handle.init();

		initCallback = callback;

		browserWin = pi.vcall.webViewNativeHandle;

		pi.worker.handle.createContext(browserWin, createRenderRes);
	};

	// 回调函数带有一个参数：context
	module.setCallback = function (draw, resize) {
		sceneDraw = draw;
		sceneReize = resize;
	};

	// 开始3D渲染，返回缓冲区句柄
	module.beginRender = function () {
		var buf = pi.cbuffer.create();
		pi.cbuffer.writeInt8(buf, RENDER_BEGIN);
		return buf;
	};

	/**
	 * 结束渲染
	 * buf: int, beginRender的返回值
	 */
	module.endRender = function (buf) {

		// 渲染网页内容
		renderPage(buf);

		pi.cbuffer.writeInt8(buf, RENDER_END);
		pi.cbuffer.writeInt(buf, CHECK_OVERFLOW_FLAG);

		sendRender(buf);
	};

	/**
	 * 设置相机
	 * pos: pi.math.vec3, 相机的位置
	 * upVec: pi.math.vec3, 相机的向上的向量
	 * frstumHandle: int, frstum的C句柄
	 */
	module.setCamera = function (buf, pos, upVec, frstumHandle) {
		var i;

		pi.cbuffer.writeInt8(buf, RENDER_3D_CAMERA);

		pi.cbuffer.writeFloat(buf, pos.x);
		pi.cbuffer.writeFloat(buf, pos.y);
		pi.cbuffer.writeFloat(buf, pos.z);

		pi.cbuffer.writeFloat(buf, upVec.x);
		pi.cbuffer.writeFloat(buf, upVec.y);
		pi.cbuffer.writeFloat(buf, upVec.z);

		pi.cbuffer.writeData(buf, frstumHandle, pi.render.t3d.getFrustumByteSize());
		
		pi.cbuffer.writeInt(buf, CHECK_OVERFLOW_FLAG);
	};

	/**
	 * 渲染天空盒
	 * buf: Number, beginRender的返回值
	 * box: RefResource, 天空盒
	 * lt：RefResource, 左面纹理
	 * rt：RefResource, 右面纹理
	 * tp：RefResource, 上面纹理
	 * bm：RefResource, 下面纹理
	 * ft：RefResource, 前面纹理
	 * bk：RefResource, 后面纹理
	 */
	module.drawSkybox = function (buf, box, lt, rt, tp, bm, ft, bk) {

		pi.cbuffer.writeInt8(buf, RENDER_3D_SKYBOX);

		// 天空盒句柄
		pi.cbuffer.writePointer(buf, box.handle);

		// 纹理句柄
		pi.cbuffer.writePointer(buf, lt.handle);
		pi.cbuffer.writePointer(buf, rt.handle);
		pi.cbuffer.writePointer(buf, tp.handle);
		pi.cbuffer.writePointer(buf, bm.handle);
		pi.cbuffer.writePointer(buf, ft.handle);
		pi.cbuffer.writePointer(buf, bk.handle);

		pi.cbuffer.writeInt(buf, CHECK_OVERFLOW_FLAG);
	};

	/**
	 * 渲染地形
	 * buf: Number, beginRender的返回值
	 * tr: RefResource, 地形
	 * mat: pi.math.mat4, 世界矩阵
	 * tex1: RefResource, 基础纹理1
	 * countTex1: {width: *, depth: *}，平铺数量
	 * tex2: RefResource, 基础纹理2
	 * countTex2: {width: *, depth: *}，平铺数量
	 * alpha: RefResource, 基础混合纹理
	 * texArr: [tex1, alpha1, tex2, alpha2, ...], 里面都是RefResource
	 * countTexArr: [countW1, countD1, countW2, countD2, ...]，uint
	 */
	module.drawTerrain = function (buf, tr, mat, tex1, countTex1, tex2, countTex2, alpha, texArr, countTexArr) {
		var i, h;

		pi.cbuffer.writeInt8(buf, RENDER_3D_TERRAIN);

		// worldMat为4*4的float型矩阵，字节数为：4 * 16
		pi.cbuffer.writeData(buf, mat, 4 * 16);

		pi.cbuffer.writePointer(buf, tr.handle);
		pi.cbuffer.writePointer(buf, tex1.handle);
		pi.cbuffer.writeInt(buf, countTex1.width);
		pi.cbuffer.writeInt(buf, countTex1.depth);

		pi.cbuffer.writePointer(buf, tex2.handle);
		pi.cbuffer.writeInt(buf, countTex2.width);
		pi.cbuffer.writeInt(buf, countTex2.depth);

		pi.cbuffer.writePointer(buf, alpha.handle);

		for (i = 0; i < 2 * TERRAIN_EXT_NUM; i += 2) {
			h = (countTexArr && countTexArr[i]) ? countTexArr[i] : 0;
			pi.cbuffer.writeInt(buf, h);
		}

		for (i = 1; i < 2 * TERRAIN_EXT_NUM; i += 2) {
			h = (countTexArr && countTexArr[i]) ? countTexArr[i] : 0;
			pi.cbuffer.writeInt(buf, h);
		}

		for (i = 0; i < 2 * TERRAIN_EXT_NUM; i += 2) {
			h = texArr[i] ? texArr[i].handle : 0;
			pi.cbuffer.writePointer(buf, h);
		}

		for (i = 1; i < 2 * TERRAIN_EXT_NUM; i += 2) {
			h = texArr[i] ? texArr[i].handle : 0;
			pi.cbuffer.writePointer(buf, h);
		}

		pi.cbuffer.writeInt(buf, CHECK_OVERFLOW_FLAG);
	};

	/**
	 * 渲染网格
	 * buf: int, beginRender的返回值
	 * mesh: RefResource,网格数据
	 * tex: RefResource,纹理数据
	 * numSKMat：int, 骨骼局部矩阵的数量
	 * sKMat：int，骨骼局部矩阵句柄
	 * posVec: pi.math.vec3, 网格的位置
	 *	用于计算和相机的距离 受根骨骼和世界矩阵的影响
	 * blend: 1代表不透明，2代表半透明
	 * mat: pi.math.mat4, 世界矩阵
	 * isRenderAABB: int, 值为1表示渲染AABB，0表示不渲染
	 */
	module.drawMesh = function (buf, mesh, tex, numSKMat, skMat, posVec, blend, mat, isRenderAABB) {

		pi.cbuffer.writeInt8(buf, RENDER_3D_MESH);

		pi.cbuffer.writePointer(buf, mesh.handle);
		pi.cbuffer.writePointer(buf, tex ? tex.handle : 0);

		// 材质数组
		pi.cbuffer.writeBinary(buf, null, 0);

		pi.cbuffer.writeInt(buf, numSKMat);
		pi.cbuffer.writePointer(buf, skMat);

		pi.cbuffer.writeFloat(buf, posVec.x);
		pi.cbuffer.writeFloat(buf, posVec.y);
		pi.cbuffer.writeFloat(buf, posVec.z);

		pi.cbuffer.writeInt(buf, blend);
		pi.cbuffer.writeInt(buf, isRenderAABB ? 1 : 0);

		// 16个float型
		pi.cbuffer.writeData(buf, mat, 4 * 16);

		pi.cbuffer.writeInt(buf, CHECK_OVERFLOW_FLAG);
	};

	/**
	 * 初始化粒子系统
	 * lineArr: pi.math.vec3 Array
	 *		当为undefined时候，表示无线段数组
	 *		当长度为1时，表示从一个点发射
	 *		当长度大于1时，必须为双数，每两个点代表一条线段
	 *		所有线段最好预处理为长度相等
	 *	返回：int，缓冲区句柄
	 */
	module.initParSys = function (lineArr) {

		var i, n, f32Arr, buf = pi.cbuffer.create();

		if (!lineArr) {
			pi.cbuffer.writeBinary(buf, null, 0);
		} else {
			n = 0;
			// lineArr的元素为vec3，就是3个浮点数
			f32Arr = pi.lang.createF32Array(3 * lineArr.length);
			for (i = 0; i < lineArr.length; i += 1) {
				f32Arr[n] = lineArr[i].x;
				n += 1;

				f32Arr[n] = lineArr[i].y;
				n += 1;

				f32Arr[n] = lineArr[i].z;
				n += 1;
			}
			// f32Arr每个元素是float，4字节
			pi.cbuffer.writeBinary(buf, f32Arr, 4 * f32Arr.length);
		}

		// 粒子数量
		pi.cbuffer.writeInt(buf, 30);

		// 粒子生命周期，单位：毫秒
		pi.cbuffer.writeInt(buf, 10000);
		pi.cbuffer.writeInt(buf, 10000);

		// 粒子显示周期，单位：毫秒
		pi.cbuffer.writeInt(buf, 6000);
		pi.cbuffer.writeInt(buf, 6000);

		// 初始发射角度，单位：度
		pi.cbuffer.writeFloat(buf, 0.0);
		pi.cbuffer.writeFloat(buf, 0.0);

		// 初始速度大小，单位：像素/秒
		pi.cbuffer.writeFloat(buf, 60.0);
		pi.cbuffer.writeFloat(buf, 60.0);

		// 速度采用球面坐标，其中phi角，单位：度
		pi.cbuffer.writeFloat(buf, 0.0);
		pi.cbuffer.writeFloat(buf, 360.0);

		// 速度采用球面坐标，其中theta角，单位：度
		pi.cbuffer.writeFloat(buf, 60.0);
		pi.cbuffer.writeFloat(buf, 60.0);

		// 线性加速度
		pi.cbuffer.writeFloat(buf, 0.0);

		// 阻力系数
		pi.cbuffer.writeFloat(buf, 0.0);

		// 方向加速度：x
		pi.cbuffer.writeFloat(buf, 0.0);

		// 方向加速度：y
		pi.cbuffer.writeFloat(buf, -20.0);

		// 方向加速度：z
		pi.cbuffer.writeFloat(buf, 0.0);

		// 粒子纹理
		pi.cbuffer.writePointer(buf, 0);
		// 纹理坐标数组
		pi.cbuffer.writeBinary(buf, null, 0);

		// 动画时间
		pi.cbuffer.writeInt(buf, 1);

		// 起始宽度
		pi.cbuffer.writeFloat(buf, 10.0);
		pi.cbuffer.writeFloat(buf, 10.0);

		// 起始高度
		pi.cbuffer.writeFloat(buf, 10.0);
		pi.cbuffer.writeFloat(buf, 10.0);

		// 起始alpha
		pi.cbuffer.writeInt8(buf, 255);
		pi.cbuffer.writeInt8(buf, 255);

		// 起始red
		pi.cbuffer.writeInt8(buf, 255);
		pi.cbuffer.writeInt8(buf, 255);

		// 起始green
		pi.cbuffer.writeInt8(buf, 0);
		pi.cbuffer.writeInt8(buf, 0);

		//  起始blue
		pi.cbuffer.writeInt8(buf, 0);
		pi.cbuffer.writeInt8(buf, 0);

		// 起始自旋速度：单位：度/秒
		pi.cbuffer.writeFloat(buf, 0.0);
		pi.cbuffer.writeFloat(buf, 0.0);

		// 终止宽度
		pi.cbuffer.writeFloat(buf, 10.0);
		pi.cbuffer.writeFloat(buf, 10.0);

		// 终止高度
		pi.cbuffer.writeFloat(buf, 10.0);
		pi.cbuffer.writeFloat(buf, 10.0);

		// 终止alpha
		pi.cbuffer.writeInt8(buf, 255);
		pi.cbuffer.writeInt8(buf, 255);

		// 终止red
		pi.cbuffer.writeInt8(buf, 255);
		pi.cbuffer.writeInt8(buf, 255);

		// 终止green
		pi.cbuffer.writeInt8(buf, 0);
		pi.cbuffer.writeInt8(buf, 0);

		//  终止blue
		pi.cbuffer.writeInt8(buf, 0);
		pi.cbuffer.writeInt8(buf, 0);

		// 终止自旋速度：单位：度/秒
		pi.cbuffer.writeFloat(buf, 0.0);
		pi.cbuffer.writeFloat(buf, 0.0);

		// 残影采样时间：单位：毫秒
		pi.cbuffer.writeInt(buf, 150);

		// 残影alpha残留系数
		pi.cbuffer.writeFloat(buf, 0.93);

		// 随机种子
		pi.cbuffer.writeInt(buf, 123456789);
		pi.cbuffer.writeInt(buf, 987654321);

		return buf;
	};

	/**
	 * 渲染粒子系统
	 * buf: Int, beginRender的返回值
	 * parBuf：Int, initParSys的返回值
	 * meshID: Int，绑定的网格id
	 * meshID: Int，绑定的骨骼id
	 * mat：pi.math.mat4, 世界矩阵
	 * ms: 当前系统时间，单位：毫秒
	 */
	module.drawParSys = function (buf, parBuf, meshID, boneID, mat, ms) {

		pi.cbuffer.writeInt8(buf, RENDER_3D_PARSYS);
		pi.cbuffer.writeBuffer(buf, parBuf);

		pi.cbuffer.writeInt(buf, meshID);
		pi.cbuffer.writeInt(buf, boneID);

		pi.cbuffer.writeData(buf, mat, 4 * 16);

		pi.cbuffer.writeInt(buf, ms);

		pi.cbuffer.writeInt(buf, CHECK_OVERFLOW_FLAG);
	};

	return module;
});